// 导入sequelize内置的数据类型，这些数据类型对应数据库的表里的不同类型
const { DataTypes } = require("sequelize");

const seq = require("../db/seq");

// 模型是 Sequelize 的本质. 模型是代表数据库中表的抽象。

/**
 * 创建(定义)模型（定义表）
 * 创建模型有两种方式：
 * 一种：通过调用Sequelize实例的define('模型名')方法，es：sequelize.define('User', {属性}); =》创建一个模型名为 User 的模型，该模型指向一个也名为 User 的表。
 * 另一种：通过扩展Model，如：const { Model } = require('sequelize');class User extends Model {}
 *
 * 表名推断：
 * 请注意，在以上两种方法中，都从未明确定义表名(Users)。但是，给出了模型名称(User)。
 * 默认情况下，当未提供表名时，Sequelize 会自动将模型名的复数写法用作表名（如：User => Users; zd_user => zd_users）。
 * 这种复数是通过称为 inflection 的库在后台完成的，因此可以正确计算不规则的复数(例如 person -> people)。
 * 若在模型配置中手动配置了表名称，则以手动配置的表名称为准。
 *
 * 在一个项目中，一般会给模型名加上一个前缀，这代表是一个统一的项目。
 */
const User = seq.define(
  "zd_users",
  // 模型属性，要和表的字段一一对应
  {
    // id属性会被 Sequelize 自动创建管理
    user_name: {
      type: DataTypes.STRING, // 该字段的数据类型
      allowNull: false, // 该字段的值是否允许为空
      unique: true, // 该字段的值是否是唯一的
      comment: "用户名，唯一", // 该字段的注释
    },
    password: {
      type: DataTypes.CHAR(64),
      allowNull: false,
      comment: "密码",
    },
    is_admin: {
      type: DataTypes.BOOLEAN, // TINYINT(1)
      allowNull: false,
      defaultValue: 0,
      comment: "是否为管理员? 0:不是管理员(默认); 1:是管理员。",
    },
  },
  // 模型配置
  {
    // 若不想自动将模型名复数并将其用作表名，可以强制表名称等于模型名称
    // freezeTableName: true, // 是否强制表名称等于模型名称
    // 也可以直接直接告诉 Sequelize 表名称
    tableName: "zd_users", // 指定表名称
    timestamps: true, // 是否自动创建 createdAt(创建时刻的时间戳) 和 updatedAt(最新更新的时间戳) 字段
  },
);

/**
 * 模型同步（即同步到数据库，在数据库中创建表，首次执行完后注释掉代码）
 * 通过此调用Sequelize将自动对数据库执行SQL查询
 * 注意：这仅更改数据库中的表，而不是更改js端的模型。
 */
// User.sync({
//   force: true, // force为true时，若数据库中已经存在该表，则会先强制删除该表，再创建该表；force为false时(不配置该属性时默认为false)，若数据库中已经存在该表，则不会再创建该表
// });

module.exports = User;
